import 'dart:math';

import 'package:analyzer/dart/element/element.dart';
import 'package:build/src/builder/build_step.dart';
import 'package:method_info/method_info.dart';
import 'package:source_gen/source_gen.dart';



class MethodInfoGenerator extends GeneratorForAnnotation<MethodInfo>{

  final bool requiredParameters;
  MethodInfoGenerator({this.requiredParameters = true});
  
  static const String comma = ",";
  static const String lineDelimiter = "\n";
  @override
  String generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep) {
    dynamic classElement;
    if(element is ClassElement || element is MixinElement){
      classElement = element;
    }
    StringBuffer all = StringBuffer("//${element.runtimeType}$lineDelimiter");
    if(classElement != null){
      int methodIndex = 0;
      List<MethodElement> methods = classElement.methods;
      int methodLen = methods.length;
      for(MethodElement methodElement in methods){
        all.write('String get ${methodElement.displayName}Name => "${methodElement.displayName}";$lineDelimiter');
        /*FunctionElement? functionElement;
        if(element is FunctionElement){
          functionElement = element;
        }*/
        StringBuffer paramsHead = StringBuffer();
        StringBuffer paramsBody = StringBuffer();
        // if(functionElement != null){
        int len = methodElement.parameters.length;
        int index = 0;
        while(index < len){
          ParameterElement parameterElement = methodElement.parameters[index];
          if(requiredParameters ? parameterElement.isRequiredNamed : parameterElement.isOptionalNamed){
            paramsHead.write(handleParamHead(parameterElement));
            paramsBody.write(handleParamBody(parameterElement));
            if(index + 1 < len){
              paramsHead.write(comma);
              paramsBody.write(comma);
            }
          }
          index ++;
        }
        all.write('Map<String, dynamic> ${methodElement.displayName}Params(${paramsHead.toString()}) =>'
            ' <String, dynamic>{${paramsBody.toString()}};');
        if(methodIndex + 1 < methodLen){
          all.write(lineDelimiter);
        }
        // }
        methodIndex ++;
      }

    }


    return all.toString();
  }

  String handleParamBody(ParameterElement e){
    return '"${e.displayName}":  ${e.displayName}';
  }

  String handleParamHead(ParameterElement e){
    return '${e.type} ${e.displayName}';
  }
}
